package com.qk.state.service;

import com.qk.entity.Business;
import com.qk.enums.BusinessEvent;
import com.qk.enums.BusinessState;
import com.qk.exception.BusinessException;
import com.qk.mapper.BusinessMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.support.DefaultStateMachineContext;
import org.springframework.stereotype.Service;

/**
 * 商机状态机服务类
 * 只负责状态流转逻辑，不操作数据库
 * @author 28188
 */
@Slf4j
@Service
public class BusinessStateMachineService {

    @Autowired
    @Qualifier("BusinessStateMachine")
    private StateMachine<BusinessState, BusinessEvent> stateMachine;

    @Autowired
    private BusinessMapper businessMapper;

    /**
     * 执行状态流转（不做数据库操作）
     *
     * @param businessId 商机ID
     * @param event      要触发的事件
     * @return 新状态（由状态机计算结果得出）
     */
    public BusinessState sendEvent(Integer businessId, BusinessEvent event) {
        // 1️⃣ 从数据库读取当前状态
        Business business = businessMapper.selectById(businessId);
        if (business == null) {
            throw new BusinessException("商机不存在");
        }

        BusinessState currentState = BusinessState.fromCode(business.getStatus());

        try {
            // 2️⃣ 重置状态机到当前状态
            resetStateMachine(currentState);

            // 3️⃣ 发送事件
            boolean accepted = stateMachine.sendEvent(event);

            if (!accepted) {
                throw new BusinessException("状态流转失败，不支持的事件：" + event +
                        "，当前状态：" + currentState.getDesc());
            }

            // 4️⃣ 返回新状态（不更新数据库，由外层业务处理）
            return stateMachine.getState().getId();

        } catch (Exception e) {
            log.error("状态机执行异常", e);
            throw new BusinessException("状态机执行异常：" + e.getMessage(), e);
        }
    }

    /**
     * 重置状态机到指定状态
     */
    private void resetStateMachine(BusinessState state) {
        // 停止状态机
        stateMachine.stop();

        // 重置状态
        stateMachine.getStateMachineAccessor()
                .doWithAllRegions(access -> {
                    access.resetStateMachine(
                            new DefaultStateMachineContext<>(state, null, null, null)
                    );
                });

        // 启动状态机
        stateMachine.start();
    }
}